﻿using System.IO;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using Nasa8x.Core;

namespace Nasa8x.Web.UI
{
    public abstract class Page : System.Web.UI.Page
    {
        
        protected bool IsHtmlOptimize { get; set; }


        #region Fix For Url Rewriter

        protected override void OnInit(System.EventArgs e)
        {
            base.OnInit(e);
            Form.Action = Request.RawUrl;
        }
        #endregion


        #region FixFormNameAttribute
        private static string FixFormNameAttribute(string _Input)
        {
            return Regex.Replace(_Input, @"(?<beforeName><form.*?)(name="".*?"")(?<afterName>.*?>)",
                 new MatchEvaluator(NameStateMatchEvaluator));
        }

        private static string NameStateMatchEvaluator(Match _Match)
        {
            return _Match.Groups["beforeName"].Value + _Match.Groups["afterName"].Value;
        }

        #endregion

        #region FixDoPostback

        private string FixDoPostback(string _Html)
        {
            Control _form = FindForm();

            return Regex.Replace(_Html, @"theform\s+=\s+document\..*?;",
                string.Format("theform = document.getElementById(\"{0}\");",
                _form.ClientID)
                );
        }


        private Control FindForm()
        {
            ControlCollection _targetCollection = Controls;

            /*   if (this.Controls[0].GetType().BaseType.BaseType.ToString().IndexOf("MasterPage") >= 0)
               {
                   targetCollection = this.Controls[0].Controls;
               }
            */
            foreach (Control _current in _targetCollection)
            {
                if (_current.GetType() == typeof(HtmlForm))
                    return _current;
            }

            return null;
        }


        #endregion

        #region OptimizeHtml

        private static readonly Regex _REGEX_BETWEEN_TAGS = new Regex(@">\s*<", RegexOptions.Singleline);
        private static readonly Regex _REGEX_HTML_LINE_BREAKS = new Regex(@"\r\n", RegexOptions.Compiled);
        private static readonly Regex _JAVASCRIPT_TAGS = new Regex(@"<script\s[^>]*>([\w\W]*?)</script>", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        private static readonly Regex _TEXTAREA_TAGS = new Regex(@"<textarea\s[^>]*>([\w\W]*?)</textarea>", RegexOptions.Singleline | RegexOptions.IgnoreCase);
        private static readonly Regex _REGEX_TAB_SPACES = new Regex(@"\t*", RegexOptions.Compiled | RegexOptions.IgnoreCase);


        /// <summary>
        /// Replace white space and line break
        /// </summary>
        /// <param name="_html"></param>
        /// <returns></returns>

        public static string HtmlOptimize(string _html)
        {

            _html = _JAVASCRIPT_TAGS.Replace(_html, new MatchEvaluator(JavaScriptMatch));
            _html = _REGEX_BETWEEN_TAGS.Replace(_html, "> <");
            if (!_TEXTAREA_TAGS.IsMatch(_html))
            {
                _html = _REGEX_TAB_SPACES.Replace(_html, string.Empty);
                _html = _REGEX_HTML_LINE_BREAKS.Replace(_html, string.Empty);
            }

            return _html;

        }



        private static string JavaScriptMatch(Match _m)
        {
            //Regex JAVASCRIPT_LINE_COMMENT = new Regex(@"//.*",RegexOptions.Singleline);

            if (_m.Groups[1].Success && !string.IsNullOrEmpty(_m.Groups[1].Value))
                return _m.ToString().Replace(_m.Groups[1].Value, string.Format("/*<![CDATA[*/{0}/*]]>*/", new ScriptPacker(ScriptPacker.PackerEncoding.None, true, false).Pack(_m.Groups[1].Value)));
            return _m.ToString();
        }

        #endregion

        #region Moving ViewState

        private static string MovingViewState(string _html)
        {

            int _startPoint = _html.IndexOf("<input type=\"hidden\" name=\"__VIEWSTATE\"");

            if (_startPoint >= 0)
            {

                int _endPoint = _html.IndexOf("/>", _startPoint) + 2;
                string _viewstateInput = string.Format("<div>{0}</div>", _html.Substring(_startPoint, _endPoint - _startPoint));
                _html = _html.Remove(_startPoint, _endPoint - _startPoint);
                int _formEndStart = _html.IndexOf("</form>");

                if (_formEndStart >= 0)
                {
                    _html = _html.Insert(_formEndStart, _viewstateInput);
                }
            }
            return _html;

        }

        #endregion

        protected override void RenderChildren(HtmlTextWriter _Output)
        {

            if (Request.Headers["X-MicrosoftAjax"] == "Delta=true")
                goto Finish;

            if (IsHtmlOptimize)
            {
                StringWriter _stringWriter = new StringWriter();
                base.RenderChildren(new HtmlTextWriter(_stringWriter));
                string _html = _stringWriter.GetStringBuilder().ToString();
                _html = MovingViewState(_html);
                _html = FixFormNameAttribute(_html);
                _html = FixDoPostback(_html);
                _html = HtmlOptimize(_html);
                _Output.Write(_html);

                return;
            }

        Finish:

            base.RenderChildren(_Output);

        }

    }
}
